#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
#![feature(extern_types)]
extern crate libc;
use primary::alloc_testing::*;
use primary::hash_table::*;
use primary::compare_pointer::*;
use primary::compare_string::*;
use primary::compare_int::*;
use primary::hash_pointer::*;
use primary::hash_string::*;
use primary::hash_int::*;
extern "C" {
    pub type _HashTable;
    pub type _HashTableEntry;
    fn sprintf(_: *mut libc::c_char, _: *const libc::c_char, _: ...) -> libc::c_int;
    fn atoi(__nptr: *const libc::c_char) -> libc::c_int;
    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    fn __assert_fail(
        __assertion: *const libc::c_char,
        __file: *const libc::c_char,
        __line: libc::c_uint,
        __function: *const libc::c_char,
    ) -> !;
                                                                        }
#[no_mangle]
pub static mut value1: libc::c_int = 1 as libc::c_int;
#[no_mangle]
pub static mut value2: libc::c_int = 2 as libc::c_int;
#[no_mangle]
pub static mut value3: libc::c_int = 3 as libc::c_int;
#[no_mangle]
pub static mut value4: libc::c_int = 4 as libc::c_int;
#[no_mangle]
pub static mut allocated_keys: libc::c_int = 0 as libc::c_int;
#[no_mangle]
pub static mut allocated_values: libc::c_int = 0 as libc::c_int;
#[no_mangle]
pub extern "C" fn generate_hash_table() -> *mut HashTable {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut buf: [libc::c_char; 10] = [0; 10];
    let mut value: *mut libc::c_char = std::ptr::null_mut();
    let mut i: libc::c_int = 0;

    hash_table = hash_table_new(
        Some(string_hash),
        Some(string_equal),
    );

    while i < 10000 {
        unsafe {
            sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, i);
            value = alloc_test_strdup(buf.as_mut_ptr());
        }

        hash_table_insert(hash_table, value as HashTableKey, value as HashTableValue);

        i += 1;
    }

    hash_table_register_free_functions(
        hash_table,
        None,
        Some(alloc_test_free),
    );

    hash_table
}
#[no_mangle]
pub extern "C" fn test_hash_table_new_free() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();

    unsafe {
        hash_table = hash_table_new(
            Some(int_hash),
            Some(int_equal),
        );
    }

    assert!(!hash_table.is_null(), "hash_table should not be NULL");

    let hash_table_box = unsafe { Box::from_raw(hash_table) };

    unsafe {
        hash_table_insert(
            hash_table,
            &mut value1 as *mut libc::c_int as HashTableKey,
            &mut value1 as *mut libc::c_int as HashTableValue,
        );
        hash_table_insert(
            hash_table,
            &mut value2 as *mut libc::c_int as HashTableKey,
            &mut value2 as *mut libc::c_int as HashTableValue,
        );
        hash_table_insert(
            hash_table,
            &mut value3 as *mut libc::c_int as HashTableKey,
            &mut value3 as *mut libc::c_int as HashTableValue,
        );
        hash_table_insert(
            hash_table,
            &mut value4 as *mut libc::c_int as HashTableKey,
            &mut value4 as *mut libc::c_int as HashTableValue,
        );
    }

    hash_table = Box::into_raw(hash_table_box);

    unsafe {
        hash_table_free(hash_table);
    }
}
#[no_mangle]
pub extern "C" fn test_hash_table_insert_lookup() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut buf: [libc::c_char; 10] = [0; 10];
    let mut value: *mut libc::c_char = std::ptr::null_mut();
    let mut i: libc::c_int = 0;

    unsafe {
        hash_table = generate_hash_table();
    }

    let hash_table_box = unsafe { Box::from_raw(hash_table) };
    assert_eq!(hash_table_num_entries(hash_table), 10000);

    i = 0;
    while i < 10000 {
        unsafe {
            sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, i);
            value = hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) as *mut libc::c_char;
        }

        assert_eq!(unsafe { strcmp(value, buf.as_mut_ptr()) }, 0);
        i += 1;
    }

    unsafe {
        sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, -1);
        assert!(hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey).is_null());

        sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, 10000);
        assert!(hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey).is_null());

        sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, 12345);
        hash_table_insert(
            hash_table,
            buf.as_mut_ptr() as HashTableKey,
            alloc_test_strdup(b"hello world\0" as *const u8 as *const libc::c_char) as HashTableValue,
        );

        value = hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) as *mut libc::c_char;
        assert_eq!(strcmp(value, b"hello world\0" as *const u8 as *const libc::c_char), 0);
    }

    hash_table = Box::into_raw(hash_table_box);
    unsafe {
        hash_table_free(hash_table);
    }
}
#[no_mangle]
pub extern "C" fn test_hash_table_remove() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut buf: [libc::c_char; 10] = [0; 10];

    unsafe {
        hash_table = generate_hash_table();
    }

    let hash_table_box = unsafe { Box::from_raw(hash_table) };

    assert_eq!(
        hash_table_num_entries(hash_table),
        10000,
        "hash_table_num_entries(hash_table) == NUM_TEST_VALUES"
    );

    unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const libc::c_char,
            5000,
        );
    }

    assert!(
        !hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey).is_null(),
        "hash_table_lookup(hash_table, buf) != NULL"
    );

    hash_table_remove(hash_table, buf.as_mut_ptr() as HashTableKey);

    assert_eq!(
        hash_table_num_entries(hash_table),
        9999,
        "hash_table_num_entries(hash_table) == 9999"
    );

    assert!(
        hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey).is_null(),
        "hash_table_lookup(hash_table, buf) == NULL"
    );

    unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const libc::c_char,
            -1,
        );
    }

    hash_table_remove(hash_table, buf.as_mut_ptr() as HashTableKey);

    assert_eq!(
        hash_table_num_entries(hash_table),
        9999,
        "hash_table_num_entries(hash_table) == 9999"
    );

    hash_table = Box::into_raw(hash_table_box);

    unsafe {
        hash_table_free(hash_table);
    }
}
#[no_mangle]
pub extern "C" fn test_hash_table_iterating() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut iterator: HashTableIterator = _HashTableIterator {
        hash_table: std::ptr::null_mut(),
        next_entry: std::ptr::null_mut(),
        next_chain: 0,
    };
    let mut count: libc::c_int = 0;

    hash_table = unsafe { generate_hash_table() };

    count = 0;

    unsafe { hash_table_iterate(hash_table, &mut iterator) };

    while unsafe { hash_table_iter_has_more(&mut iterator) } != 0 {
        unsafe { hash_table_iter_next(&mut iterator) };
        count += 1;
    }

    assert_eq!(count, 10000, "count == NUM_TEST_VALUES");

    let mut pair: HashTablePair = unsafe { hash_table_iter_next(&mut iterator) };
    assert!(pair.value.is_null(), "pair.value == HASH_TABLE_NULL");

    unsafe { hash_table_free(hash_table) };

    hash_table = hash_table_new(
        Some(int_hash),
        Some(int_equal),
    );

    unsafe { hash_table_iterate(hash_table, &mut iterator) };

    assert_eq!(unsafe { hash_table_iter_has_more(&mut iterator) }, 0, "hash_table_iter_has_more(&iterator) == 0");

    unsafe { hash_table_free(hash_table) };
}
#[no_mangle]
pub extern "C" fn test_hash_table_iterating_remove() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut iterator: HashTableIterator = _HashTableIterator {
        hash_table: std::ptr::null_mut(),
        next_entry: std::ptr::null_mut(),
        next_chain: 0,
    };
    let mut buf: [libc::c_char; 10] = [0; 10];
    let mut val: *mut libc::c_char = std::ptr::null_mut();
    let mut pair: HashTablePair = _HashTablePair {
        key: std::ptr::null_mut(),
        value: std::ptr::null_mut(),
    };
    let mut count: libc::c_int = 0;
    let mut removed: libc::c_uint = 0;
    let mut i: libc::c_int = 0;

    unsafe {
        hash_table = generate_hash_table();
    }

    count = 0;
    removed = 0;

    unsafe {
        hash_table_iterate(hash_table, &mut iterator);
    }

    while unsafe { hash_table_iter_has_more(&mut iterator) } != 0 {
        pair = unsafe { hash_table_iter_next(&mut iterator) };
        val = pair.value as *mut libc::c_char;

        if unsafe { atoi(val) } % 100 == 0 {
            unsafe {
                hash_table_remove(hash_table, val as HashTableKey);
            }
            removed = removed.wrapping_add(1);
        }
        count += 1;
    }

    assert_eq!(removed, 100);
    assert_eq!(count, 10000);
    assert_eq!(
        unsafe { hash_table_num_entries(hash_table) },
        (10000 as libc::c_uint).wrapping_sub(removed)
    );

    i = 0;
    while i < 10000 {
        unsafe {
            sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const libc::c_char, i);
        }
        if i % 100 == 0 {
            assert!(unsafe { hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) }.is_null());
        } else {
            assert!(!unsafe { hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) }.is_null());
        }
        i += 1;
    }

    unsafe {
        hash_table_free(hash_table);
    }
}
#[no_mangle]
pub extern "C" fn new_key(mut value: libc::c_int) -> *mut libc::c_int {
    let mut result: *mut libc::c_int = std::ptr::null_mut();

    unsafe {
        result = alloc_test_malloc(std::mem::size_of::<libc::c_int>() as libc::c_ulong)
            as *mut libc::c_int;
        assert!(!result.is_null(), "Memory allocation failed");
    }

    let mut result_box = unsafe { Box::from_raw(result) };
    *result_box = value;
    unsafe { allocated_keys += 1; }

    Box::into_raw(result_box)
}
#[no_mangle]
pub extern "C" fn free_key(mut key: *mut libc::c_void) {
    let key_box = unsafe { Box::from_raw(key) };
    unsafe {
        alloc_test_free(Box::into_raw(key_box));
        allocated_keys -= 1;
        assert!(allocated_keys >= 0, "allocated_keys should not be negative");
    }
}
#[no_mangle]
pub extern "C" fn new_value(mut value: libc::c_int) -> *mut libc::c_int {
    let mut result: *mut libc::c_int = std::ptr::null_mut();

    result = alloc_test_malloc(std::mem::size_of::<libc::c_int>() as libc::c_ulong) as *mut libc::c_int;
    let mut result_box = unsafe { Box::from_raw(result) };
    assert!(!result.is_null(), "Memory allocation failed");
    *result_box = value;
    unsafe { allocated_values += 1; }

    Box::into_raw(result_box)
}
#[no_mangle]
pub extern "C" fn free_value(mut value: *mut libc::c_void) {
    let value_box = unsafe { Box::from_raw(value) };
    unsafe {
        alloc_test_free(Box::into_raw(value_box));
        allocated_values -= 1;
        assert!(allocated_values >= 0, "allocated_values cannot be negative");
    }
}
#[no_mangle]
pub extern "C" fn test_hash_table_free_functions() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut key: *mut libc::c_int = std::ptr::null_mut();
    let mut value: *mut libc::c_int = std::ptr::null_mut();
    let mut i: libc::c_int = 0;

    hash_table = hash_table_new(
        Some(int_hash),
        Some(int_equal),
    );
    hash_table_register_free_functions(
        hash_table,
        Some(free_key),
        Some(free_value),
    );

    unsafe { allocated_values = 0; }
    i = 0;
    while i < 10000 {
        key = new_key(i);
        value = new_value(99);
        hash_table_insert(hash_table, key as HashTableKey, value as HashTableValue);
        i += 1;
    }

    assert_eq!(unsafe { allocated_keys }, 10000, "allocated_keys == NUM_TEST_VALUES");
    assert_eq!(unsafe { allocated_values }, 10000, "allocated_values == NUM_TEST_VALUES");

    i = 10000 / 2;
    hash_table_remove(hash_table, &mut i as *mut libc::c_int as HashTableKey);
    assert_eq!(unsafe { allocated_keys }, 9999, "allocated_keys == NUM_TEST_VALUES - 1");
    assert_eq!(unsafe { allocated_values }, 9999, "allocated_values == NUM_TEST_VALUES - 1");

    key = new_key(10000 / 3);
    value = new_value(999);
    assert_eq!(unsafe { allocated_keys }, 10000, "allocated_keys == NUM_TEST_VALUES");
    assert_eq!(unsafe { allocated_values }, 10000, "allocated_values == NUM_TEST_VALUES");

    hash_table_insert(hash_table, key as HashTableKey, value as HashTableValue);
    assert_eq!(unsafe { allocated_keys }, 9999, "allocated_keys == NUM_TEST_VALUES - 1");
    assert_eq!(unsafe { allocated_values }, 9999, "allocated_values == NUM_TEST_VALUES - 1");

    hash_table_free(hash_table);
    assert_eq!(unsafe { allocated_keys }, 0, "allocated_keys == 0");
    assert_eq!(unsafe { allocated_values }, 0, "allocated_values == 0");
}
#[no_mangle]
pub unsafe extern "C" fn test_hash_table_out_of_memory() {}
#[no_mangle]
pub extern "C" fn test_hash_iterator_key_pair() {
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut iterator: HashTableIterator = _HashTableIterator {
        hash_table: std::ptr::null_mut(),
        next_entry: std::ptr::null_mut(),
        next_chain: 0,
    };
    let mut pair: HashTablePair = _HashTablePair {
        key: std::ptr::null_mut(),
        value: std::ptr::null_mut(),
    };

    hash_table = hash_table_new(
        Some(int_hash),
        Some(int_equal),
    );
    hash_table_insert(
        hash_table,
        unsafe { &mut value1 as *mut libc::c_int as HashTableKey },
        unsafe { &mut value1 as *mut libc::c_int as HashTableValue },
    );
    hash_table_insert(
        hash_table,
        unsafe { &mut value2 as *mut libc::c_int as HashTableKey },
        unsafe { &mut value2 as *mut libc::c_int as HashTableValue },
    );
    hash_table_iterate(hash_table, &mut iterator);

    while hash_table_iter_has_more(&mut iterator) != 0 {
        pair = hash_table_iter_next(&mut iterator);
        let key: *mut libc::c_int = pair.key as *mut libc::c_int;
        let val: *mut libc::c_int = pair.value as *mut libc::c_int;

        unsafe {
            assert!(*key == *val, "Assertion failed: *key == *val");
        }
    }

    hash_table_free(hash_table);
}
